#include <pcap.h>
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <thread>
#include <vector>
#include <iomanip>

using namespace std;
struct EthernetFrame
{
    uint8_t dest_mac[6];  // 目的MAC地址
    uint8_t src_mac[6];   // 源MAC地址
    uint16_t ethertype;   // 以太网类型
    uint8_t payload[512]; // 数据载荷（最小46字节以太网帧）
};
void print_hex(const uint8_t *data, size_t length)
{
    for (size_t i = 0; i < length; ++i)
    {
        // 打印每个字节的16进制表示
        cout << hex << setw(2) << setfill('0') << (int)data[i] << " ";

        // 每16个字节换行一次
        if ((i + 1) % 16 == 0)
        {
            cout << endl;
        }
    }
    cout << endl;
}
void read_packets(pcap_t *handle)
{
    struct pcap_pkthdr *header;
    const uint8_t *packet;

    while (true)
    {
        // pcap_next_ex 会阻塞直到捕获到数据包
        int res = pcap_next_ex(handle, &header, &packet);
        if (res == 1)
        {
            // 捕获到了数据包
            cout << "Captured a packet of size " << header->len << " bytes." << endl;

            // 打印数据包的内容（16进制）
            cout << "Packet content (hex):" << endl;
            print_hex(packet, header->len);

            // 打印可打印字符
            cout << "Packet content (ASCII):" << endl;
            for (size_t i = 0; i < header->len; ++i)
            {
                char ch = isprint(packet[i]) ? packet[i] : '.';
                cout << ch;
            }
            cout << endl
                 << endl;
        }
        else if (res == 0)
        {

            cout << "No packet captured, still waiting..." << endl;
        }
        else
        {
            cerr << "Error capturing packet: " << pcap_geterr(handle) << endl;
            break;
        }
    }
}

void send_packet(pcap_t *handle, const string &message)
{
    EthernetFrame frame;
    memset(frame.dest_mac, 0xFF, 6);                           // 广播目的 MAC 地址
    uint8_t src_mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; // 源 MAC 地址
    memcpy(frame.src_mac, src_mac, 6);
    frame.ethertype = htons(0x0800); // 以太网类型（IPv4）

    size_t payload_len = message.size();
    if (payload_len > sizeof(frame.payload))
    {
        cerr << "Message too long, truncating to 512 bytes." << endl;
        payload_len = sizeof(frame.payload);
    }

    memcpy(frame.payload, message.c_str(), payload_len);
    memset(frame.payload + payload_len, 0, sizeof(frame.payload) - payload_len);

    if (pcap_sendpacket(handle, reinterpret_cast<const uint8_t *>(&frame), 14 + payload_len) != 0)
    {
        cerr << "Error sending packet: " << pcap_geterr(handle) << endl;
        return;
    }

    cout << "Packet sent: " << message << endl;
}
struct Command
{
    std::string name;
    std::string json;
};
std::vector<Command> commands = {
    {"powerOff", "{\"Light\":{\"Power\":false}}"},
    {"powerON", "{\"Light\":{\"Power\":true}}"},
    {"addSchedule", "{\"Schedule\":{\"Schedules\":[{\"action\":{\"Switch\":{\"Power\":true}},\"id\":\"1VR1\",\"name\":\"test\",\"operation\":\"add\",\"triggers\":[{\"d\":0,\"m\":919}]}]}}"},
    {"removeSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"remove\"}]}}"},
    {"enableSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"enable\"}]}}"},
    {"disableSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"disable\"}]}}"}};
int main()
{

    const char *device = "usb0";   // 要打开的网卡
    char errbuf[PCAP_ERRBUF_SIZE]; // 错误缓冲区

    // 打开网卡
    // pcap_t *handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
    pcap_t *handle = pcap_open_live(device, BUFSIZ, 1, 0, errbuf);
    if (handle == nullptr)
    {
        cerr << "Error opening device " << device << ": " << errbuf << endl;
        return 1;
    }

    cout << "Opened device " << device << " successfully." << endl;

    // 启动接收线程
    thread reader_thread(read_packets, handle);

    // 主线程用于发送数据
    std::string input;
    while (true)
    {
        std::cout << "input command、'exit'、'list': ";
        std::getline(std::cin, input);

        if (input == "exit")
        {
            break;
        }
        else if (input == "list")
        {
            for (const auto &cmd : commands)
            {
                std::cout << cmd.name << std::endl;
            }
            continue;
        }
        // 查找对应的 JSON 数据
        std::string jsonStr;
        bool found = false;
        for (const auto &cmd : commands)
        {
            if (cmd.name == input)
            {
                jsonStr = cmd.json;
                found = true;
                break;
            }
        }
        send_packet(handle, jsonStr);
    }
    reader_thread.join();
    return 0;
}